package cn.com.ldns.opentetris.activity;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import cn.com.ldns.opentetris.R;
import cn.com.ldns.opentetris.common.BoxType;
import cn.com.ldns.opentetris.common.FloatUtil;
import cn.com.ldns.opentetris.shape.BaseBox;
import cn.com.ldns.opentetris.shape.BaseShape;
import cn.com.ldns.opentetris.shape.Cube;
import cn.com.ldns.opentetris.shape.ShapeFactory;
import cn.com.ldns.opentetris.shape.Square;
import cn.com.ldns.opentetris.shape.model.Acceleration;
import cn.com.ldns.opentetris.shape.model.Position;
public class HomeActivity extends GLSurfaceActivity implements OnClickListener {
	private static final int WHAT_GAME_OVER = 0;
	private static final int WHAT_UPDATE_SCORE = 1;
	
	private HashMap<String, BaseShape> shapes = new HashMap<String, BaseShape>();

	private ShapeFactory shapeFactory ;
	private List<Integer> textures;
	private Button leftBtn;
	private Button downBtn;
	private Button rightBtn;
	private Button changeBtn;
	private TextView scoreTev;
	private BaseBox currentBox;
	private boolean[][] tetrisData;
	private Handler handler;
	private boolean running = true;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.main);
        
        shapeFactory = ShapeFactory.getInstance();
        
        glSurfaceView = (GLSurfaceView) findViewById(R.id.tetrisView);
        glSurfaceView.setRenderer(this);
        glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        
        leftBtn = (Button) findViewById(R.id.leftBtn);
        leftBtn.setOnClickListener(this);
        downBtn = (Button) findViewById(R.id.downBtn);
        downBtn.setOnClickListener(this);
        rightBtn = (Button) findViewById(R.id.rightBtn);
        rightBtn.setOnClickListener(this);
        changeBtn = (Button) findViewById(R.id.changeBtn);
        changeBtn.setOnClickListener(this);
        scoreTev =  (TextView) findViewById(R.id.scoreTev);
        
        tetrisData = new boolean[15][21];
        
        handler = new Handler() {
			public void handleMessage(android.os.Message msg) {
				switch (msg.what) {
				case WHAT_GAME_OVER:
					AlertDialog.Builder dialogBuilder = new Builder(HomeActivity.this);
			        dialogBuilder.setTitle("Tip");
			        dialogBuilder.setMessage("Game Over！");
			        dialogBuilder.setPositiveButton("Try again", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int arg1) {
							dialog.dismiss();
							// 初始化
							tetrisData = new boolean[15][21];
							shapes.clear();
							scoreTev.setText("0");
							running = true;
							DrawScene();
						}
					});
			        dialogBuilder.setNeutralButton("Exit", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int arg1) {
							dialog.cancel();
							finish();
						}
					});
			        dialogBuilder.create().show();
					break;
				case WHAT_UPDATE_SCORE:
					scoreTev.setText("" + (Integer.parseInt(scoreTev.getText().toString()) + 15));
					break;
				default:
					break;
				}
			};
		};
        
        // 每隔一秒绘制一次
		DrawScene();
    }
    
    @Override
	public void onDrawFrame(final GL10 gl) {
    	super.onDrawFrame(gl);
    	// 绘制背景
    	DrawBackground(gl);
    	
    	// 绘制图形
    	gl.glLoadIdentity();
		gl.glTranslatef(0, 0, -10);
		currentBox.draw(gl);
		
		// 判断是否停止下落
		boolean stop = false;
		for (Cube cube : currentBox.getCubes()) {
			Position p = cube.getPosition();
			int xIndex = (int)FloatUtil.valueOf(p.getX() * 10 / 2.0f) + 7;
			int yIndex = (int)(-FloatUtil.valueOf(p.getY() * 10 / 2.0f) + 10.5f);
			if (p.getY() <= -1.9f || tetrisData[xIndex][yIndex + 1]) {
				stop = true;
				currentBox.stopBox();
				break;
			}
		}
		
		if (stop) {
			for (Cube cube : currentBox.getCubes()) {
				Position position = cube.getPosition();
				int iIndex = (int)FloatUtil.valueOf(position.getX() * 10 / 2.0f) + 7;
				int jIndex = (int)(-FloatUtil.valueOf(position.getY() * 10 / 2.0f) + 10.5f);
				tetrisData[iIndex][jIndex] = true;
				shapes.put(position.getX() + "x" + position.getY(), cube);
			}

			// 消除处理
			for (Position position : currentBox.getPositions()) {
				boolean clear = true;
				int jIndex = (int)(-FloatUtil.valueOf(position.getY() * 10 / 2.0f) + 10.5f);
				for(int i = 0;i < 15;i++) {
					clear = clear && tetrisData[i][jIndex];
					if (!clear) break; 
				}
				if (clear) {
					for(int i = 0;i < 15;i++) {
						float x = FloatUtil.valueOf((i - 7) / 5.0f);
						shapes.remove(x + "x" + position.getY());
						tetrisData[i][jIndex] = false;
					}
					android.os.Message msg = handler.obtainMessage();
                    msg.what = WHAT_UPDATE_SCORE;
                    msg.sendToTarget();
					
					HashMap<String, BaseShape> temp = new HashMap<String, BaseShape>();
					Iterator<String> iter = shapes.keySet().iterator();
					while (iter.hasNext()) {
						BaseShape box = shapes.get(iter.next());
						Position ps = box.getPosition();
						if (ps.getY() > position.getY()) {
							ps.setY(FloatUtil.valueOf(ps.getY() - 0.2f));
						}
						temp.put(ps.getX() + "x" + ps.getY(), box);
					}
					shapes = temp;

					tetrisData = new boolean[15][21]; 
					Iterator<String> iterator = shapes.keySet().iterator();
					while (iterator.hasNext()) {
						Position ps = shapes.get(iterator.next()).getPosition();
						int i = (int)FloatUtil.valueOf(ps.getX() * 10 / 2.0f) + 7;
						int j = (int)(-FloatUtil.valueOf(ps.getY() * 10 / 2.0f) + 10.5f);
						tetrisData[i][j] = true;
					}
				} else {
					if (position.getY() >= 1.5f) {
						android.os.Message msg = handler.obtainMessage();
	                    msg.what = WHAT_GAME_OVER;
	                    msg.sendToTarget();
	                    running = false;
					}
				}
			}
			// 创建新图形
			CreateNewShape();
		}
		
		// 绘制已停止的图形
		Iterator<String> iter = shapes.keySet().iterator();
		while (iter.hasNext()) {
			String key = iter.next();
			BaseShape box = shapes.get(key);
			gl.glLoadIdentity();
    		gl.glTranslatef(0, 0, -10);
    		box.draw(gl);
		}
    }
    
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
    	super.onSurfaceChanged(gl, width, height);
    }
    
    public void onSurfaceCreated(GL10 gl, EGLConfig config){
    	super.onSurfaceCreated(gl, config);
    	BindTextures(gl);
    }
    

	@Override
	public void onClick(View view) {
		int targetId = view.getId();
		switch (targetId) {
			case R.id.leftBtn:
				leftMove();
				break;
			case R.id.downBtn:
				downMove();
				break;
			case R.id.rightBtn:
				rightMove();
				break;
			case R.id.changeBtn:
				changeBox();
				break;
			default:
				break;
		}
	}
	
	// 每个一秒绘制场景
	private void DrawScene() {
        CreateNewShape();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while(running) {
						glSurfaceView.requestRender();
						Thread.sleep(1000);	
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
    
    // 绘制背景
    private void DrawBackground(GL10 gl) {

    	// 坐标
    	float[] vertex = new float[]{
    		1.5f, 4f, 0.0f,
    		-1.5f, 4f, 0.0f,
    		-1.5f, -4f, 0.0f,
    		1.5f, -4f, 0.0f
    	};
    	// 颜色
    	float[] color = new float[]{
    		1f, 0f, 0f, 0f,
    		1f, 0f, 0f, 0f,
    		1f, 0f, 0f, 0f,
    		1f, 0f, 0f, 0f
    	};
    	gl.glTranslatef(0, -2f, 0);
    	gl.glRotatef(90, -1, 0, 0);
    	Square s = new Square(vertex, color);
    	s.draw(gl);
    	
    }
    
    // 随机创建图形
    private void CreateNewShape() {
    	int ordinal = (int) Math.floor(Math.random() * BoxType.values().length);
    	BaseBox box = shapeFactory.createBox(BoxType.valueOf(ordinal));
    	box.setBoxAcceleration(new Acceleration(0, -0.2f, 0));
    	if(textures != null) 
    		box.setBoxTexture(textures.get(0));
    	box.moveBox(new Position(0, 1.5f, 0));
    	currentBox = box;
    }
    
    // 向左移动
    private void leftMove() {
    	boolean canMove = true;
    	Position[] positions = currentBox.getPositions();
    	for (Position p : positions) {
    		int xIndex = (int)FloatUtil.valueOf(p.getX() * 10 / 2.0f) + 7;
    		int yIndex = (int)(-FloatUtil.valueOf(p.getY() * 10 / 2.0f) + 10.5f);
			if (p.getX() - 0.2f < -1.5f || tetrisData[xIndex - 1][yIndex]) {
				canMove = false;
				break;
			}
		}
		if (canMove) {
			currentBox.moveBox(new Position(-0.2f, 0, 0));
		}
    }
    
    // 向右移动
    private void rightMove() {
    	boolean canMove = true;
    	Position[] positions = currentBox.getPositions();
    	for (Position p : positions) {
    		int xIndex = (int)FloatUtil.valueOf(p.getX() * 10 / 2.0f) + 7;
    		int yIndex = (int)(-FloatUtil.valueOf(p.getY() * 10 / 2.0f) + 10.5f);
			if (p.getX() + 0.2f > 1.5f || tetrisData[xIndex + 1][yIndex]) {
				canMove = false;
				break;
			}
		}
		if (canMove) {
			currentBox.moveBox(new Position(0.2f, 0, 0));
		}
    }  
    
    // 向下移动
    private void downMove() {
    	Position[] positions = currentBox.getPositions();
    	float maxY = -100f;
    	for (Position p : positions) {
    		int xIndex = (int)FloatUtil.valueOf(p.getX() * 10 / 2.0f) + 7;
    		int yIndex = (int)(-FloatUtil.valueOf(p.getY() * 10 / 2.0f) + 10.5f);

    		int y;
    		float dy = 0f;
    		for(y = yIndex + 1; y < 21; y++) {
    			if (tetrisData[xIndex][y]) {
    				dy = FloatUtil.valueOf((10.5f - y) * 2.0f / 10 - p.getY() + 0.4f);
    				break;
    			}
    		}
    		
    		if (y >= 21) {
    			dy = FloatUtil.valueOf(-1.9f - p.getY() + 0.2f);
    		}
    		if (dy > maxY) maxY = dy;
    	}
    	System.out.println(maxY);
		currentBox.moveBox(new Position(0, maxY, 0));
		glSurfaceView.requestRender();
    }
    
    private void changeBox() {
    	currentBox.changeState();
    }
    
    //绑定纹理
    private void BindTextures(GL10 gl){
    	int[]texture = new int[1];
    	gl.glGenTextures(1, texture,0); 
    	gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
    	
    	gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    	gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    	gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    	gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
    	
    	Bitmap bmp = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_add);
    	GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

    	bmp.recycle();
    	bmp = null;
    	
    	if(textures==null)
    		textures = new LinkedList<Integer>();
    	textures.add(texture[0]);
    }
}